<?PHP
// vim: set expandtab tabstop=4 shiftwidth=4:
// +----------------------------------------------------------------------+
// | SAPID: XML Sapiens Engine Demonstrator                               |
// +----------------------------------------------------------------------+
// | Author:  Max Baryshnikov aka Mephius <mb@rg.by>	                  |
// | Copyright (c) 2004 Max Baryshnikov                                   |
// | http://sapid.sourceforge.net	                                      |
// +----------------------------------------------------------------------+
// | This source file is free software; you can redistribute it and/or    |
// | modify it under the terms of the GNU Lesser General Public           |
// | License as published by the Free Software Foundation; either         |
// | version 2.1 of the License, or (at your option) any later version.   |
// |                                                                      |
// | This source file is distributed in the hope that it will be useful,  |
// | but WITHOUT ANY WARRANTY; without even the implied warranty of       |
// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU    |
// | Lesser General Public License for more details.                      |
// +----------------------------------------------------------------------+
// Release: 13.11.04 (dd/mm/yy)
// $Id: vdb.lib.php,v 1.7 2006/02/20 08:26:49 sheiko Exp $



class sapi_vdb {
	var $parser;
	var $depth;
	var $filename;
	var $objdata;
	var $id_of_row;
	var $last_name;
	var $filter;
	var $new_id;


	/**
	* @return true
	* @desc sapi_vdb class constructor
	*/
	function sapi_vdb($filename=false){

		if($filename) {
			if($this->filename AND $filename!=$this->filename) $this->close();
			$this->filename=$filename;
		}

		$this->filename=$filename;
		$this->objdata=array();
		$this->new_id=time();
		return true;
	}

	function close(){
		//$this->filename=false;
		$this->objdata=array();
		$this->new_id=0;
		$this->parser=0;
		$this->depth=0;
		$this->id_of_row=0;
		$this->last_name=0;
		$this->filter=0;
		return true;
	}

	function set_filter($filter){
		$code="";
		if(is_array($filter)){
			foreach ($filter as $key=>$exp) {
				if($key=="DATE_CREATE") $code='strpos(\$attrs["DATE_CREATE"], "'.$exp.'")!==false';
				if($key=="ID") $code.=(($code!="" and $exp!="")?' AND \$attrs["ID"]=='.$exp."":"");
			}
			$this->filter="\$pass=(" . $code . "); ";
		}
		return true;
	}

	/**
	* @return array
	* @param string $filename
	* @desc get data from xml file
	*/
	function get_data($filename=false, $commands=false){


		if($filename) {
			if($this->filename AND $filename!=$this->filename) $this->close();
			$this->filename=$filename;
		}

		switch($this->filename) {
			case "users":
			$this->filename = $root_path."usr/xml/users.xml";
			break;
		}


		$this->depth=0;
		$this->id_of_row=0;
		$this->last_name="";

		if($this->objdata) return $this->objdata;

		//if( preg_match("/_GETCONTENT_/is", $commands) ) $get_content = true; else $get_content = false;

		$this->parser = xml_parser_create();
		xml_set_object($this->parser, $this);
		xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, true);
		xml_set_element_handler($this->parser, "startElement", "endElement");
		xml_set_character_data_handler($this->parser, "characterData");

		$this->objdata = array();
		$this->depth = $this->last_name = $this->id_of_row = false;

		if(file_exists($this->filename)) {
		if (!($fp = @fopen($this->filename, "r"))) {
			//message_die("Couldn't open <b>" . $this->filename . "</b> for reading!", "Fatal Error");
		}else{
			while ($data = fread($fp, 4096)) {
				if (!xml_parse($this->parser, $data, feof($fp))) {
					//message_die("XML error: ".$this->filename);
					message_die("XML error: ".$this->filename." at line ".(int)xml_error_string(xml_get_error_code($this->parser))." column ".(int)xml_get_current_line_number($this->parser)." in file " );
				}
			}
			xml_parser_free($this->parser);
		}
		}

		$ids_c = 0;
		$ids = array();
		foreach ($this->objdata as $key=>$entry) {
			foreach ($entry as $k=>$data) {
				$this->objdata[$key][$k]=$data;
			}
			$ids[$ids_c++]=$this->objdata[$key]["ID"];
		}
		if($ids) {
			rsort($ids);
			$this->new_id = $ids[0]+1;
		}
		if( preg_match("/_ONEROW_/is", $commands) ) return $entry;
		return $this->objdata;
	}



	/**
	* @return void
	* @param XML Parser resource id $parser
	* @param string $name
	* @param array $attrs
	* @desc Start element handler
	*/
	function startElement($parser, $name, $attrs) {
		if($this->depth[$parser]==1 AND $name="ROW") {
			$this->id_of_row+=1;
			if($this->filter) @eval($this->filter);
			if (($this->filter and $pass) or $this->filter=="") {
				$this->pass=true;
				foreach ($attrs as $key=>$value) {
					$this->objdata[$this->id_of_row][$key]=$value;
				}
			}else $this->pass=false;
		}

		if($this->depth[$parser]==2 AND isset($attrs["VALUE"])) $this->objdata[$this->id_of_row][$name] = $attrs["VALUE"];
		$this->last_name = $name;
		if(!isset($this->depth[$parser])) $this->depth[$parser]=0;
		$this->depth[$parser]++;
	}
	/**
	* @return void
	* @param XML Parser resource id $parser
	* @param string $name
	* @desc End element handler
	*/
	function endElement($parser, $name) {
		$this->depth[$parser]--;
	}

	/**
	* @return void
	* @param XML Parser resource id $parser
	* @param string $data
	* @desc CData handler
	*/
	function characterData($parser, $data) {
		if($this->depth[$parser]==3 AND $data) {
			if ($this->pass) {
				if(!isset($this->objdata[$this->id_of_row][$this->last_name])) $this->objdata[$this->id_of_row][$this->last_name]="";
				$this->objdata[$this->id_of_row][$this->last_name] .= $data;
			}
		}
	}


	/*
	Appropriate values of $data["post_action"]
	ADDNEWIPROW
	ADDROW
	CHANGEROW
	UPDATEROW
	Source array $data["ROW"][..]
	*/

	function save_data_row($filename=false, $data=false, $unique_ip=false){

		if($filename) $this->filename=$filename;
		if (!$data) $data=$_POST;
		if($data["ROW"]) $data["row"] = $data["ROW"];
		if($this->filename AND $data["row"]) {

			$objdata=$this->get_data();


			$IP = getenv("REMOTE_ADDR");
			$DATE_CREATE = date("Y-m-d H:i:s");
			if(!$data["row"]["IP"]) $data["row"]["IP"] = $IP; else $IP = $data["row"]["IP"];
			if(!$data["row"]["DATE_CREATE"]) $data["row"]["DATE_CREATE"] = $DATE_CREATE; else $DATE_CREATE = $data["row"]["DATE_CREATE"];

			if($objdata and ($unique_ip ||  $data["post_action"]=="ADDNEWIPROW")) {
				foreach($objdata as $fetch) {
					$fetch_date_create=strtotime($fetch['DATE_CREATE']);
					$current_date=strtotime(date('Y-m-d H:i:s'));
					if ($fetch["IP"]==$IP && ($current_date-$fetch_date_create<=(VDB_SAMEIP_WRITE_DELAY*60))) $flag_ip_false = true;

				}
			}

			$stream = "<data>\n";
			if((!$flag_ip_false AND $data["post_action"]=="ADDNEWIPROW" ) OR $data["post_action"] =="ADDROW" OR $data["post_action"] == "CHANGEROW" ) {
				// Adding new row
				$stream .= "\t<row ip=\"".$IP."\" id=\"".$this->new_id."\" date_create=\"".$DATE_CREATE."\">\n";

				if (is_array($data["row"])) {
					$this->objdata = array_merge(array($data["row"]), $this->objdata);

					foreach($data["row"] as $key => $value) {
						if($key!="IP" AND $key!="DATE_CREATE"  AND $key!="ID") {
							if( ini_get("magic_quotes_gpc")!= "Off" ) $value = stripslashes($value);
							$stream .= "\t\t<".$key."><![CDATA[".str_replace("’", "'", $value)."]]></" . $key . ">\n";
						}
					}
				}
				$stream .= "\t</row>\n";
			}

			if($data["post_action"] != "CHANGEROW" ) {
				// Restoring old rows
				if (is_array($objdata))
				foreach($objdata as $inx => $fetch) {
					if($data["post_action"] == "UPDATEROW" AND $fetch["ID"]==$data["row"]["ID"]) {
						$this->objdata[$inx] = $fetch = $data["row"];
					}
					$stream .= "\t<row ip=\"".$fetch["IP"]."\" id=\"".$fetch["ID"]."\" date_create=\"".$fetch["DATE_CREATE"]."\">\n";
					foreach($fetch as $key => $value) {
						if($key!="IP" AND $key!="DATE_CREATE"  AND $key!="ID")
						$stream .= "\t\t<".strtolower($key)."><![CDATA[".str_replace("’", "'", $value)."]]></" . strtolower($key) . ">\n";
					}
					$stream .= "\t</row>\n";
				}
			}
			$stream .= "</data>";

			if($fp = @fopen($this->filename, "w+")) {
				@fwrite($fp, $stream);
				@fclose($fp);
				@chmod($filename, 0666);
			} else message_die("Can not rewrite file ".$this->filename);

		}
		return true;
	}

	function save_objdata($objdata){
		$stream="<data>\n";
		$IP = getenv("REMOTE_ADDR");
		$DATE_CREATE = date("Y-m-d H:i:s");
		if (is_array($objdata))
		foreach($objdata as $fetch) {
			$stream .= "\t<row ip=\"".($fetch["IP"]?$fetch["IP"]:$IP)."\" id=\"".$fetch["ID"]."\" date_create=\"".($fetch["DATE_CREATE"]?$fetch["DATE_CREATE"]:$DATE_CREATE)."\">\n";
			foreach($fetch as $key => $value) {
				if( get_magic_quotes_gpc() ) $value = stripslashes($value);
				if(strtolower($key)!="ip" AND strtolower($key)!="date_create" AND strtolower($key)!="id")
				$stream .= "\t\t<".strtolower($key)."><![CDATA[".str_replace("’", "'", $value)."]]></" . strtolower($key) . ">\n";
			}
			$stream .= "\t</row>\n";
		}
		$stream .= "</data>";
		if(!validateXML($stream)) {  trigger_error("Can not save content changes. Input data contains invalid XML.", E_USER_NOTICE); return false; }
		$fp = fopen($this->filename, "w+");
		$result=@fwrite($fp, $stream);
		@fclose($fp);
		@chmod($filename, 0666);
		return $result;
	}


	function delete_data_row($arg_value, $arg_key="DATE_CREATE"){
		$objdata=$this->get_data();

		foreach ($objdata as $key=>$entry) {
			if ($entry[$arg_key]==$arg_value) {
				unset($objdata[$key]);
				break;
			}
		}

		$result=$this->save_objdata($objdata);
		return $result;
	}

	function change_data_row($date_create, $new_row){
		$objdata=$this->get_data();
		foreach ($objdata as $key=>$entry) {
			if ($entry["DATE_CREATE"]==$date_create) {
				$new_row["DATE_CREATE"]=date("Y-m-d H:i:s");
				$new_row["IP"] = getenv("REMOTE_ADDR");
				$objdata[$key]=$new_row;
				break;
			}
		}

		$result=$this->save_objdata($objdata);
		return $result;
	}

	function get_userdata($login, $password) {
		$data = $this->get_data($root_path."usr/xml/users.xml");
		if($data) {
			foreach($data as $row) {
				if($row["LOGIN"]==$login AND $row["PASSWORD"]==$password AND $password!=""  AND $login!="") return $row;
			}

		} else return false;
		return false;
	}


}


?>